#include "Parser.h"

Console::Console()
{
	this->linea=NULL;
	this->pipe=NULL;
	this->mode="r";
}

void Console::dispose()
{
#ifdef WIN32
	_pclose(pipe);
#else
	pclose(pipe);
#endif
pipe=NULL;
}

Console::~Console()
{
	if(pipe!=NULL)
		this->dispose();
	if(linea!=NULL)
		free(linea);
	
}
bool Console::run(const std::string &command, const std::string &arguments)
{
string com= command;
com+=" ";
com+=arguments;
//Si quiere volver a correr un comando, reviso que haya liberado el pipe.
if(pipe!=NULL)
	this->dispose();

#ifdef WIN32
	pipe=_popen(com.c_str(),mode.c_str());
#else
	pipe=popen(com.c_str(),mode.c_str());
#endif

if(pipe==NULL)
{
     return false;
	
}
else
     return true;
}

bool Console::getLine(string &line)
{
 
  if(getLinea(line))
 {	
	 //borro los saltos de linea virtuales
	 string::size_type pos;
	 
	 pos= line.rfind("\\n");
	 
	while(pos!=string::npos)
	 {
		 line.replace(pos,2,"\n");

		 pos= line.find("\\n",++pos);
	 }
	return true;
 }
 else
	return false;
}
bool Console::getLinea(string &salida )
{
	int mPow = 0;
	
	/*Asigno una cantidad inicial de memoria*/
	int mTecho = (int)(MIN_LINEA * pow(2.0, mPow));
	int res = 0;
	int ind = 0;

	/*Si no esta en fin de archivo leo la linea*/
	if (!feof(pipe))
	{
		while (((res = fgetc(pipe)) != FIN_LINEA) && (!feof(pipe)))
		{
			if (linea == NULL)
				/*Reservo espacio inicial*/
				linea = (char *)malloc(sizeof(char) * mTecho);
			
			/*Si supere la capacidad maxima del string, lo agrando*/
			if (ind > (mTecho - 1))
			{
				mPow++;
				mTecho = MIN_LINEA * (int)pow(2.0, mPow);
				linea = (char *)realloc(linea, sizeof(char) * mTecho);
			}
			
			(linea)[ind] = (char)res;
			ind++;

		}
		if(res=='\n')
		{
			if (ind > (mTecho - 1))
			{
				mTecho +=1;
				linea = (char *)realloc(linea, sizeof(char) * mTecho);
			}
			else if (ind == 0)
			{
				linea = (char*)malloc(sizeof(char));
			}
		(linea)[ind] = FIN_CADENA;
		salida.assign(linea,strlen(linea));
		
		free(linea);
		linea=NULL;
		return true;

		}
		else
		{
		return false;
		}

	}
	
	return false;
}
Parser::Parser(const std::string &command)
{
	this->command=command;

}

unsigned int Parser::Parse(const std::string &url, Feed & feed)
{	
	//En este string pongo lo que me responde el plugin
	string answer;
	time_t fecha;
	unsigned int status;
	
	//si ejecuta el comando 
	if(console.run(this->command,url))
	{
	
	console.getLine(answer);
	
		if(answer.compare("feedok")==0)
		{

			//calcula la fecha de ultima actualizacion
			fecha=time(NULL);

			feed.setDate(fecha);

			//leo nombre del Feed
			console.getLine(answer);
			feed.setName(answer);
	
			//leo url del Feed
			console.getLine(answer);
			feed.setURL(answer);

			//Leo un titulo de noticia
			while(console.getLine(answer))
			{
			News noticia;
			noticia.setTitle(answer);
			
			//Leo la Fecha de la noticia.
			console.getLine(answer);
			fecha = atol(answer.c_str());
			noticia.setDate(fecha);

			//leo descripcion de la noticia
			console.getLine(answer);
			noticia.setDescription(answer);

			feed.addNews(noticia);

			}
		

			//Termina de usar la consola y sale
			status= Parser::feedok;
		}
		else
		{
			if(answer.compare("feedupdated")==0)
				status=Parser::feedupdated;
			else 
				if(answer.compare("feedbad")==0)
					status=Parser::feedbad;
				else
					if(answer.compare("nofeed")==0)
						status= Parser::nofeed;
					else
						status=Parser::nocommand;
		}
	}
	else//No pudo abrir la consola
		status= Parser::nocommand;

console.dispose();
return status;
}
